#ifndef _B5M_LOCKED_QUEUE_H_
#define _B5M_LOCKED_QUEUE_H_

#include "common.h"
#include "B5M_Queue.h"
#include "B5M_Thread_Mutex.h"
#include "B5M_Guard.h"
#include <queue>

B5M_BEGIN_VERSIONED_NAMESPACE_DECL


template <class T, class LockType = B5M_Thread_Mutex, typename StorageType=std::deque<T> >
class B5M_LockedQueue : public B5M_Queue<T> {

    //! Serialize access to the Queue
    LockType _lock;

    //! Storage backing the queue
    StorageType _queue;

    public:

    //! Create a LockedQueue
    B5M_LockedQueue(){};

    //! Destroy a LockedQueue
    virtual ~B5M_LockedQueue() { };

    /**
    * @see Queue::add(const T& item)
    */
    virtual void add(const T& item) {

		B5M_GUARD(LockType,obj,_lock); 
    
		_queue.push_back(item);

    }

    /**
    * @see Queue::add(const T& item, unsigned long timeout)
    */
    virtual bool add(const T& item, unsigned long timeout) 
	{
		if(_lock.acquire(timeout) == -1)
		{
			return false;
		}     
        _queue.push_back(item); 
		_lock.release();

		return true;
    }

    /**
    * @see Queue::next()
    */
    virtual bool next(T& t) 
	{    
		B5M_GUARD_RETURN(LockType,obj,_lock,false);

		if(_queue.size() == 0)
			return false;

		t = _queue.front();

		_queue.pop_front();

		return true;
    }

      
    /**
    * @see Queue::next(unsigned long timeout)
    */
    virtual bool next(T& t,unsigned long timeout) {

		if(_lock.acquire(timeout) == -1)
		{
			return false;
		} 

		if(_queue.size() == 0)
			return false;

		t = _queue.front();

		 _queue.pop_front();
      
		 _lock.release();
		return true;      
    }

    /**
    * @see Queue::size()
    */
    virtual size_t size() {

		B5M_GUARD_RETURN(LockType,obj,_lock,0);
		return _queue.size();
    }

    /**
    * @see Queue::size(unsigned long timeout)
    */
    virtual size_t size(unsigned long timeout) {

		if(_lock.acquire(timeout) == -1)
		{
			return 0;
		}  
		 return _queue.size();
		_lock.release();   
    }

	B5M_NONE_COPYABLE(B5M_LockedQueue); 
}; /* B5M_LockedQueue */

B5M_END_VERSIONED_NAMESPACE_DECL

#endif